﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;

namespace Dsl.Ped.Editor.Interfaces
{
    /// <summary>
    /// Interface that is implemented by a DSLPed editor.
    /// Any hosting application must conveniently handle the interaction with an editor via this interface.
    /// Any new implementation of the editor must implement this interface to interact with already 
    /// existing hosts.
    /// 
    /// Techniaclly, any DSLPed editor internaly handles the files as projective objects and must
    /// provide a methods for the deserialization of files into objects and backwards serialization
    /// the loaded objects back into the files.
    /// </summary>
    public interface IDslPedEditor
    {
        /// <summary>
        /// Dictionary mapping the namespace to the Projective Type
        /// </summary>
        Dictionary<string, Type> RegisteredTypes { get; }

        /// <summary>
        /// Currently opened file in the editor
        /// </summary>
        string CurrentFileName { get; }

        /// <summary>
        /// Current projective type of an object loaded into the editor
        /// </summary>
        Type CurrentProjectiveType { get; }

        /// <summary>
        /// Load the file of a given name
        /// </summary>
        /// <param name="fileName">Name of the file to be loaded</param>
        /// <returns>Object that the file of a name <see cref="fileName"/> was deserialized to</returns>
        object LoadFile(string fileName);

        /// <summary>
        /// Load a file of a given name using the given <see cref="xmlReader"/>
        /// </summary>
        /// <param name="fileName">Name of the file to be loaded</param>
        /// <param name="xmlReader"><see cref="XmlReader"/> used for the deserialization of a file</param>
        /// <returns>Object that the file of a name <see cref="fileName"/> was deserialized to with the use of <see cref="xmlReader"/></returns>
        object LoadFile(string fileName, XmlReader xmlReader);

        /// <summary>
        /// Open the already loaded file, if it wasn't loaded yet
        /// </summary>
        void OpenLoadedFile();

        /// <summary>
        /// Load and open a file in the editor
        /// </summary>
        /// <param name="fileName">Name of the file to be opened</param>
        void LoadAndOpenFile(string fileName);

        /// <summary>
        /// Load and open a file in the editor using a given <see cref="XmlReader"/>
        /// </summary>
        /// <param name="fileName">Name of a file to be loaded and opened</param>
        /// <param name="xmlReader"><see cref="XmlReader"/> used for the loadeing of a file</param>
        void LoadAndOpenFile(string fileName, XmlReader xmlReader);

        /// <summary>
        /// Save the current projective object to the file of a current name
        /// </summary>
        /// <returns>True if the process was successfull, False otherwise</returns>
        bool SaveFile();

        /// <summary>
        /// Save the current projective object to the file of a given file name
        /// </summary>
        /// <param name="fileName">Name of the file used for the saving of a projective object</param>
        /// <returns>True if the process was successfull, False otherwise</returns>
        bool SaveFile(string fileName);

        /// <summary>
        /// Create a new projective object of a given type
        /// </summary>
        /// <param name="projectiveType">Required type of the object</param>
        /// <returns>True if the object was created successfully, False otherwise</returns>
        bool NewProjectiveObject(Type projectiveType);

        /// <summary>
        /// Create a new projective object of a given type, use the default object as a prototype if not null.
        /// This is useful when we need to create new projective object with some preset values, like name of parameters, attributes, etc.
        /// </summary>
        /// <param name="projectiveType">Required type of the object</param>
        /// <param name="defaultObject">Default instance of the object</param>
        /// <returns>True if the object was created successfully, False otherwise</returns>
        bool NewProjectiveObject(Type projectiveType, object defaultObject);

        /// <summary>
        /// Serialize current projective object into <see cref="XDocument"/>
        /// </summary>
        /// <returns>Current projective object serialized into <see cref="XDocument"/></returns>
        XDocument SerializeProjectiveObject();

        /// <summary>
        /// Gets or sets the indication if the current projective object was changed
        /// </summary>
        bool IsDirty { get; set; }
    }
}
